Imports NineBit.LgLcd_Net
Imports System.Drawing

''' <summary>
''' The LCD Class
''' </summary>
''' <remarks>
''' Contains the code used to make interfacing with the LCD simpler.
''' </remarks>
Public Class lcd

    'The LCD context objects
    Private connectContext As LgLcd.lgLcdConnectContext = New LgLcd.lgLcdConnectContext()
    Private openContext As LgLcd.lgLcdOpenContext = New LgLcd.lgLcdOpenContext()

    'The lgLcdBitmap160x43x1 used to represent the screen
    Private LCDBitmap As LgLcd.lgLcdBitmap160x43x1 = New LgLcd.lgLcdBitmap160x43x1

    'The delegates used to recieve the ConfigPress and ButtonPress routines
    Public Delegate Function ConfigPress(ByVal connection As Integer, ByVal pcontext As System.IntPtr) As Integer
    Public Delegate Function Butpress(ByVal device As Integer, ByVal dwButtons As Integer, ByVal pContext As System.IntPtr) As Integer
    Private LCDButtonPress As Butpress
    Private LCDConfigPress As ConfigPress

    ''' <summary>
    ''' New Instance of Class
    ''' </summary>
    ''' <param name="ButtonPressSubroutine">
    ''' The routine to return to when a LCD button is pressed.
    ''' </param>
    ''' <param name="ConfigSubroutine">
    ''' The routine to return to when the Configuarion button is pressed in the LCD Manger.
    ''' </param>
    Public Sub New(ByVal ButtonPressSubroutine As Butpress, ByVal ConfigSubroutine As ConfigPress)
        'When an instance of the class is created, the delegates are passed the routines to return to.
        LCDButtonPress = ButtonPressSubroutine
        LCDConfigPress = ConfigSubroutine
    End Sub

    ''' <summary>
    ''' The Initialization procedure to set up the connection to the LCD
    ''' </summary>
    ''' <param name="apptitle">Title used on the LCD menu.</param>
    ''' <remarks></remarks>
    Public Sub InitLCD(ByVal apptitle As String)
        Dim res As Integer
        ' Initialize the LCD library
        res = LgLcd.lgLcdInit()
        HandleError(res, "lcdInit failed")

        ' Connect to the LCD library
        connectContext.appFriendlyName = apptitle
        connectContext.isAutostartable = True

        ' Use this so that when the application is run in the interface it won't be autostartable.
        ' That way you want get Visual Studio starting each time you start your PC.
#If DEBUG Then
        connectContext.isAutostartable = False
#End If

        'Set up connection and set the paramaters and callbacks
        connectContext.isPersistent = True
        connectContext.onConfigure.configCallback = AddressOf LCDConfigPress.Invoke
        connectContext.onConfigure.configContext = IntPtr.Zero
        connectContext.connection = LgLcd.LGLCD_INVALID_CONNECTION
        res = LgLcd.lgLcdConnect(connectContext)
        HandleError(res, "lgLcdConnect failed")

        ' Open the first LCD found (index 0)
        openContext.connection = connectContext.connection
        openContext.index = 0
        openContext.onSoftbuttonsChanged.softbuttonsChangedCallback = AddressOf LCDButtonPress.Invoke
        openContext.onSoftbuttonsChanged.softbuttonsChangedContext = IntPtr.Zero
        openContext.device = LgLcd.LGLCD_INVALID_DEVICE
        res = LgLcd.lgLcdOpen(openContext)
        LCDBitmap.hdr.Format = LgLcd.LGLCD_BMP_FORMAT_160x43x1
        ReDim LCDBitmap.pixels(160 * 43)
        HandleError(res, "lgLcdOpen")
    End Sub

    ''' <summary>
    ''' Draws the bitmap passed on to the LCDBitmap object
    ''' </summary>
    ''' <param name="lcdscreen">The System.Drawing.Bitmap object to draw.</param>
    ''' <remarks>Note: This does NOT update the screen! Just draws to the LCD Bitmap</remarks>
    Public Sub DrawLCD(ByVal lcdscreen As Bitmap)
        ' Create a new bitmap.
        Dim bmp As New Bitmap(lcdscreen)
        Dim rect As New Rectangle(0, 0, bmp.Width, bmp.Height)
        Dim bmpData As System.Drawing.Imaging.BitmapData = bmp.LockBits(rect, _
            Drawing.Imaging.ImageLockMode.ReadWrite, Drawing.Imaging.PixelFormat.Format24bppRgb)
        Dim ptr As IntPtr = bmpData.Scan0
        Dim bytes As Integer = bmp.Width * bmp.Height * 3
        Dim rgbValues(bytes - 1) As Byte
        Dim pix(lcdscreen.Width * lcdscreen.Height) As Byte
        Dim i As Integer = 0

        System.Runtime.InteropServices.Marshal.Copy(ptr, rgbValues, 0, bytes)
        For counter As Integer = 0 To rgbValues.Length - 1 Step 3
            LCDBitmap.pixels(i) = rgbValues(counter)
            i = i + 1
        Next
        bmp.UnlockBits(bmpData)
    End Sub

    ''' <summary>
    ''' Passes the LCDBitmap object to the LCD Screen.
    ''' </summary>
    Public Sub UpdateLCD()
        LgLcd.lgLcdUpdateBitmap(openContext.device, LCDBitmap, LgLcd.LGLCD_PRIORITY_NORMAL)
    End Sub

    ''' <summary>
    ''' Closes the connection to the LCD.
    ''' </summary>
    ''' <remarks></remarks>
    Public Sub CloseLCD()
        Dim res As Integer
        ' Close the LCD
        res = LgLcd.lgLcdClose(openContext.device)
        HandleError(res, "lgLcdClose")
        res = LgLcd.lgLcdDisconnect(connectContext.connection)
        HandleError(res, "lgLcdDisconnect failed")
        res = LgLcd.lgLcdDeInit()
        HandleError(res, "lcdDeInit failed")
    End Sub

    ''' <summary>
    ''' Handles any errors with the connection of the LCD
    ''' </summary>
    ''' <param name="res">Result of a LCD function</param>
    ''' <param name="msg">Message to display if there was an error with the function</param>
    ''' <remarks>A "res" of 0 represents a successful call.</remarks>
    Private Sub HandleError(ByVal res As Integer, ByVal msg As String)
        If res <> 0 Then
            Throw New Exception(msg)
        End If
    End Sub

End Class